// xhelper.cpp




#include "xhelper.h"


/******************************************************************************/



void XMeshCollisionTest(const stXFrame* xFrame, const stXMesh* xMesh, stCollisionInfo* collisionInfo)
{
	if (xMesh->m_numVerts==0 || xMesh->m_numTris==0) return;

	const int  numVerts				= xMesh->m_numVerts;
	const int  numTris				= xMesh->m_numTris;
	const stXMesh::stTriData* tris	= xMesh->m_tris;
	const D3DXVECTOR3* verts		= xMesh->m_verts;

	for (int i=0; i<numTris; i++)
	{
		int i0 = tris[i].vertIndx[0];
		int i1 = tris[i].vertIndx[1];
		int i2 = tris[i].vertIndx[2];

		D3DXVECTOR3 v0 = verts[i0];
		D3DXVECTOR3 v1 = verts[i1];
		D3DXVECTOR3 v2 = verts[i2];

		D3DXVec3TransformCoord(	&v0, &v0, &xFrame->m_matAnim);
		D3DXVec3TransformCoord(	&v1, &v1, &xFrame->m_matAnim);
		D3DXVec3TransformCoord(	&v2, &v2, &xFrame->m_matAnim);


		D3DXVECTOR3 hitPoint;
		bool hit = false;

		switch (collisionInfo->m_collisionType)
		{
			case stCollisionInfo::CT_TRIRAY:
			{
				hit =
				TriangleLineCollision2( collisionInfo->m_to, collisionInfo->m_from,
										v0, v1, v2,
										&hitPoint);
			}
			break;

			case stCollisionInfo::CT_TRISPHERE:
			{
				hit = 
				SphereTriangleCollision(collisionInfo->m_centre, collisionInfo->m_radius,
										  v0, v1, v2,
										  &hitPoint,
										  NULL);

			}
			break;

			default: {DBG_HALT;}
		}

		if (hit)
		{
			D3DXVECTOR3 a0 = v1 - v0;
			D3DXVECTOR3 a1 = v2 - v0;
			D3DXVECTOR3 triNorm = Cross(a0, a1);
			triNorm = Normalize(triNorm);

			D3DXVECTOR3 dirToHitSource = collisionInfo->m_from - hitPoint;
			dirToHitSource = Normalize(dirToHitSource);

			float cosAng = Dot(dirToHitSource, triNorm);
			if (cosAng<0.0f)
			{
				triNorm = -triNorm;
			}


			D3DXVECTOR3 distTo = collisionInfo->m_to - collisionInfo->m_from;
			D3DXVECTOR3 hitDistTo = hitPoint - collisionInfo->m_from;
			float penDepth = D3DXVec3Length(&(hitDistTo - distTo));

			collisionInfo->m_hasHit      = true;
			collisionInfo->m_hitPoint    = hitPoint;
			collisionInfo->m_penetration = penDepth;
			collisionInfo->m_hitDir		 = triNorm;
		}

	}

	/*
	D3DXVECTOR3 vertTrans;
	for (int i=0; i<numVerts; i++)
	{
		D3DXVec3TransformCoord(	&vertTrans, &xMesh->m_verts[i], &xFrame->m_matAnim);
		vmin->x = min(vmin->x, vertTrans.x);
		vmin->y = min(vmin->y, vertTrans.y);
		vmin->z = min(vmin->z, vertTrans.z);

		vmax->x = max(vmax->x, vertTrans.x);
		vmax->y = max(vmax->y, vertTrans.y);
		vmax->z = max(vmax->z, vertTrans.z);
	}
	*/
}

/******************************************************************************/

void XFrameCollisionTest(const stXFrame* xFrame, stCollisionInfo* collisionInfo)
{
	DBG_ASSERT(xFrame);
	DBG_ASSERT(xFrame->GetType()==X_FRAME);


	while (xFrame)
	{
		if (xFrame->m_child)
		{
			DBG_ASSERT(xFrame!=xFrame->m_child);
			XFrameCollisionTest(xFrame->m_child, collisionInfo);
		}

		stXMesh* xMesh = xFrame->m_mesh;
		while (xMesh)
		{
			XMeshCollisionTest(xFrame, xMesh, collisionInfo);
			xMesh = xMesh->m_next;
		}

		xFrame = xFrame->m_next;
	}

}

/******************************************************************************/


